home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Science / RasMol2 / abstree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-28  |  31.6 KB  |  1,086 lines  |  [TEXT/KAHL]

  1. /* abstree.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, October 1994
  4.  * Version 2.5
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <malloc.h>
  10. #endif
  11. #ifndef sun386
  12. #include <stdlib.h>
  13. #endif
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18.  
  19. #define ABSTREE
  20. #include "molecule.h"
  21. #include "abstree.h"
  22.  
  23.  
  24. #define ExprPool    16
  25. #define SetPool     4
  26.  
  27. typedef struct _SymEntry {
  28.                 struct _SymEntry __far *lft;
  29.                 struct _SymEntry __far *rgt;
  30.                 AtomSet __far *defn;
  31.                 char *ident;
  32.                 } SymEntry;
  33.  
  34. static SymEntry __far *SymbolTable;
  35. static SymEntry __far *FreeEntry;
  36. static AtomSet __far *FreeSet;
  37. static Expr *FreeExpr;
  38. static Expr FalseExpr;
  39. static Expr TrueExpr;
  40.  
  41. /* Macros for commonly used loops */
  42. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  43.                      for(group=chain->glist;group;group=group->gnext)    \
  44.                      for(aptr=group->alist;aptr;aptr=aptr->anext)
  45.  
  46.  
  47. #define BitAcidic       0x001
  48. #define BitAliphatic    0x002
  49. #define BitAromatic     0x004
  50. #define BitBasic        0x008
  51. #define BitBuried       0x010
  52. #define BitCyclic       0x020
  53. #define BitHydrophobic  0x040
  54. #define BitMedium       0x080
  55. #define BitNeutral      0x100
  56. #define BitSmall        0x200
  57.  
  58. #define BitCharged      0x009
  59. #define BitNotLarge     0x280
  60.  
  61. /* Acyclic = !Cyclic         */
  62. /* Large = !Medium && !Small */
  63. /* Polar = !Hydrophobic      */
  64. /* Surface = !Buried         */
  65.  
  66.  
  67. static int AminoProp[] = {
  68.         /*ALA*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral |
  69.                  BitSmall,
  70.         /*GLY*/  BitAliphatic | BitHydrophobic | BitNeutral | BitSmall,
  71.         /*LEU*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral,
  72.         /*SER*/  BitNeutral | BitSmall,
  73.         /*VAL*/  BitAliphatic | BitBuried | BitHydrophobic | BitMedium |
  74.                  BitNeutral,
  75.         /*THR*/  BitMedium | BitNeutral,
  76.         /*LYS*/  BitBasic,
  77.         /*ASP*/  BitAcidic | BitMedium,
  78.         /*ILE*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral,
  79.         /*ASN*/  BitMedium | BitNeutral,
  80.         /*GLU*/  BitAcidic,
  81.         /*PRO*/  BitCyclic | BitHydrophobic | BitMedium | BitNeutral,
  82.         /*ARG*/  BitBasic,
  83.         /*PHE*/  BitAromatic | BitBuried | BitCyclic | BitHydrophobic |
  84.                  BitNeutral,
  85.         /*GLN*/  BitNeutral,
  86.         /*TYR*/  BitAromatic | BitCyclic | BitNeutral,
  87.         /*HIS*/  BitAromatic | BitBasic | BitCyclic | BitNeutral,
  88.         /*CYS*/  BitBuried | BitMedium | BitNeutral,
  89.         /*MET*/  BitBuried | BitHydrophobic | BitNeutral,
  90.         /*TRP*/  BitAromatic | BitBuried | BitCyclic | BitHydrophobic |
  91.                  BitNeutral,
  92.  
  93.         /*ASX*/  BitMedium | BitNeutral,
  94.         /*GLX*/  BitNeutral,
  95.         /*PCA*/  BitCyclic | BitHydrophobic | BitMedium | BitNeutral,
  96.         /*HYP*/  BitCyclic | BitMedium | BitNeutral
  97.         };
  98.  
  99.  
  100. static void FatalExprError(ptr)
  101.     char *ptr;
  102. {
  103.     char buffer[80];
  104.  
  105.     sprintf(buffer,"Expression Error: %s!",ptr);
  106.     RasMolFatalExit(buffer);
  107. }
  108.  
  109.  
  110. #ifdef FUNCPROTO
  111. /* Function Prototypes */
  112. static AtomSet __far *SetInsert( AtomSet __far*, Atom __far* );
  113. static int IsWithinRadius( AtomSet __far*, Long );
  114. static int IsSetMember( AtomSet __far* );
  115. #endif
  116.  
  117.  
  118. static AtomSet __far *SetInsert( ptr, item )
  119.     AtomSet __far *ptr;  Atom __far *item;
  120. {
  121.     register AtomSet __far *temp;
  122.     register int i;
  123.  
  124.     if( ptr && (ptr->count<SetSize) )
  125.     {   ptr->data[ptr->count] = item;
  126.         ptr->count++;
  127.         return( ptr );
  128.     }
  129.  
  130.     if( !FreeSet )
  131.     {   temp = (AtomSet __far*)_fmalloc( SetPool*sizeof(AtomSet) );
  132.         if( !temp ) FatalExprError("Memory allocation failed");
  133.         for( i=1; i<SetPool; i++ )
  134.         {    temp->next = FreeSet;
  135.              FreeSet = temp++;
  136.         }
  137.     } else
  138.     {   temp = FreeSet;
  139.         FreeSet = temp->next;
  140.     }
  141.  
  142.     temp->data[0] = item;
  143.     temp->next = ptr;
  144.     temp->count = 1;
  145.     return( temp );
  146. }
  147.  
  148.  
  149. static int IsWithinRadius( ptr, limit )
  150.     AtomSet __far *ptr;
  151.     Long limit;
  152. {
  153.     register Atom __far *aptr;
  154.     register Long dx,dy,dz;
  155.     register Long dist;
  156.     register int i;
  157.  
  158.     while( ptr )
  159.     {   for( i=0; i<ptr->count; i++ )
  160.         {    aptr = ptr->data[i];
  161.              dx = QAtom->xorg-aptr->xorg; if( (dist=dx*dx)>limit ) continue;
  162.              dy = QAtom->yorg-aptr->yorg; if( (dist+=dy*dy)>limit ) continue;
  163.              dz = QAtom->zorg-aptr->zorg; if( (dist+=dz*dz)>limit ) continue;
  164.              return( True );
  165.         }
  166.         ptr = ptr->next;
  167.     }
  168.     return( False );
  169. }
  170.  
  171.  
  172. static int IsSetMember( ptr )
  173.     AtomSet __far *ptr;
  174. {
  175.     register int i;
  176.  
  177.     while( ptr )
  178.     {   for( i=0; i<ptr->count; i++ )
  179.             if( ptr->data[i] == QAtom )
  180.                 return( True );
  181.         ptr = ptr->next;
  182.     }
  183.     return( False );
  184. }
  185.  
  186.  
  187. void DeleteAtomSet( ptr )
  188.     AtomSet __far *ptr;
  189. {
  190.     register AtomSet __far *temp;
  191.  
  192.     if( (temp = ptr) )
  193.     {   while( temp->next )
  194.             temp = temp->next;
  195.         temp->next = FreeSet;
  196.         FreeSet = ptr;
  197.     }
  198. }
  199.  
  200.  
  201. Expr *AllocateNode()
  202. {
  203.     register Expr *ptr;
  204.     register int i;
  205.  
  206.     if( !FreeExpr )
  207.     {   ptr = (Expr*)malloc( ExprPool*sizeof(Expr) );
  208.         if( !ptr ) FatalExprError("Memory allocation failed");
  209.         for( i=1; i<ExprPool; i++ )
  210.         {   ptr->rgt.ptr = FreeExpr;
  211.             FreeExpr = ptr++;
  212.         }
  213.     } else
  214.     {   ptr = FreeExpr;
  215.         FreeExpr = ptr->rgt.ptr;
  216.     }
  217.     ptr->rgt.ptr = NULL;
  218.     ptr->lft.ptr = NULL;
  219.     return( ptr );
  220. }
  221.  
  222.  
  223. void DeAllocateExpr( expr )
  224.     Expr *expr;
  225. {
  226.     if( !expr ) return;
  227.     if( (expr == &FalseExpr) ||
  228.         (expr == &TrueExpr) ) 
  229.         return;
  230.  
  231.     if( expr->type!=OpWithin )
  232.     {   if( !(expr->type&(OpLftProp|OpLftVal)) )
  233.             DeAllocateExpr( expr->lft.ptr );
  234.         if( !(expr->type&(OpRgtProp|OpRgtVal)) )
  235.             DeAllocateExpr( expr->rgt.ptr );
  236.     } else DeleteAtomSet( expr->rgt.set );
  237.         
  238.     expr->rgt.ptr = FreeExpr;
  239.     FreeExpr = expr;
  240. }
  241.  
  242.  
  243. int GetElemNumber( aptr )
  244.     Atom __far *aptr;
  245. {
  246.     register char *ptr;
  247.     register char ch;
  248.  
  249.     ptr = ElemDesc[aptr->refno];
  250.     ch = ptr[1];
  251.  
  252.     switch( *ptr )
  253.     {   case(' '):  switch( ch )
  254.                     {   case('B'):  return(  5 );
  255.                         case('C'):  return(  6 );
  256.                         case('D'):  return(  1 );
  257.                         case('F'):  return(  9 );
  258.                         case('H'):  return(  1 );
  259.                         case('I'):  return( 53 );
  260.                         case('K'):  return( 19 );
  261.                         case('L'):  return(  1 );
  262.                         case('N'):  return(  7 );
  263.                         case('O'):  return(  8 );
  264.                         case('P'):  return( 15 );
  265.                         case('S'):  return( 16 );
  266.                         case('U'):  return( 92 );
  267.                         case('V'):  return( 23 );
  268.                         case('W'):  return( 74 );
  269.                         case('Y'):  return( 39 );
  270.                     }
  271.                     break;
  272.  
  273.         case('A'):  switch( ch )
  274.                     {   case('C'):  return( 89 );
  275.                         case('G'):  return( 47 );
  276.                         case('L'):  return( 13 );
  277.                         case('M'):  return( 95 );
  278.                         case('R'):  return( 18 );
  279.                         case('S'):  return( 33 );
  280.                         case('T'):  return( 85 );
  281.                         case('U'):  return( 79 );
  282.                     }
  283.                     break;
  284.  
  285.         case('B'):  switch( ch )
  286.                     {   case('A'):  return( 56 );
  287.                         case('E'):  return(  4 );
  288.                         case('I'):  return( 83 );
  289.                         case('K'):  return( 97 );
  290.                         case('R'):  return( 35 );
  291.                     }
  292.                     break;
  293.  
  294.         case('C'):  switch( ch )
  295.                     {   case('A'):  return( 20 );
  296.                         case('D'):  return( 48 );
  297.                         case('E'):  return( 58 );
  298.                         case('F'):  return( 98 );
  299.                         case('L'):  return( 17 );
  300.                         case('M'):  return( 96 );
  301.                         case('O'):  return( 27 );
  302.                         case('R'):  return( 24 );
  303.                         case('S'):  return( 55 );
  304.                         case('U'):  return( 29 );
  305.                     }
  306.                     break;
  307.  
  308.         case('D'):  if( ch=='Y' )
  309.                         return( 66 );
  310.                     break;
  311.  
  312.         case('E'):  if( ch=='R' )
  313.                     {   return( 68 );
  314.                     } else if( ch=='S' )
  315.                     {   return( 99 );
  316.                     } else if( ch=='U' )
  317.                         return( 63 );
  318.                     break;
  319.  
  320.         case('F'):  if( ch=='E' )
  321.                     {   return(  26 );
  322.                     } else if( ch=='M' )
  323.                     {   return( 100 );
  324.                     } else if( ch=='R' )
  325.                         return(  87 );
  326.                     break;
  327.  
  328.         case('G'):  if( ch=='A' )
  329.                     {   return( 31 );
  330.                     } else if( ch=='D' )
  331.                     {   return( 64 );
  332.                     } else if( ch=='E' )
  333.                         return( 32 );
  334.                     break;
  335.  
  336.         case('H'):  if( ch=='E' )
  337.                     {   return(  2 );
  338.                     } else if( ch=='F' )
  339.                     {   return( 72 );
  340.                     } else if( ch=='G' )
  341.                     {   return( 80 );
  342.                     } else if( ch=='O' )
  343.                         return( 67 );
  344.                     break;
  345.  
  346.         case('I'):  if( ch=='N' )
  347.                     {   return( 49 );
  348.                     } else if( ch=='R' )
  349.                         return( 77 );
  350.                     break;
  351.  
  352.         case('K'):  if( ch=='R' )
  353.                         return( 36 );
  354.                     break;
  355.  
  356.         case('L'):  if( ch=='A' )
  357.                     {   return(  57 );
  358.                     } else if( ch=='I' )
  359.                     {   return(   3 );
  360.                     } else if( (ch=='R') || (ch=='W') )
  361.                     {   return( 103 );
  362.                     } else if( ch=='U' )
  363.                         return(  71 );
  364.                     break;
  365.  
  366.         case('M'):  if( ch=='D' )
  367.                     {   return( 101 );
  368.                     } else if( ch=='G' )
  369.                     {   return(  12 );
  370.                     } else if( ch=='N' )
  371.                     {   return(  25 );
  372.                     } else if( ch=='O' )
  373.                         return(  42 );
  374.                     break;
  375.  
  376.         case('N'):  switch( ch )
  377.                     {   case('A'):  return(  11 );
  378.                         case('B'):  return(  41 );
  379.                         case('D'):  return(  60 );
  380.                         case('E'):  return(  10 );
  381.                         case('I'):  return(  28 );
  382.                         case('O'):  return( 102 );
  383.                         case('P'):  return(  93 );
  384.                     }
  385.                     break;
  386.  
  387.         case('O'):  if( ch=='S' )
  388.                         return( 76 );
  389.                     break;
  390.  
  391.         case('P'):  switch( ch )
  392.                     {   case('A'):  return( 91 );
  393.                         case('B'):  return( 82 );
  394.                         case('D'):  return( 46 );
  395.                         case('M'):  return( 61 );
  396.                         case('O'):  return( 84 );
  397.                         case('R'):  return( 59 );
  398.                         case('T'):  return( 78 );
  399.                         case('U'):  return( 94 );
  400.                     }
  401.                     break;
  402.  
  403.         case('R'):  switch( ch )
  404.                     {   case('A'):  return( 88 );
  405.                         case('B'):  return( 37 );
  406.                         case('E'):  return( 75 );
  407.                         case('H'):  return( 45 );
  408.                         case('N'):  return( 86 );
  409.                         case('U'):  return( 44 );
  410.                     }
  411.                     break;
  412.                     break;
  413.  
  414.         case('S'):  switch( ch )
  415.                     {   case('B'):  return( 51 );
  416.                         case('C'):  return( 21 );
  417.                         case('E'):  return( 34 );
  418.                         case('I'):  return( 14 );
  419.                         case('M'):  return( 62 );
  420.                         case('N'):  return( 50 );
  421.                         case('R'):  return( 38 );
  422.                     }
  423.                     break;
  424.  
  425.         case('T'):  switch( ch )
  426.                     {   case('A'):  return( 73 );
  427.                         case('B'):  return( 65 );
  428.                         case('C'):  return( 43 );
  429.                         case('E'):  return( 52 );
  430.                         case('H'):  return( 90 );
  431.                         case('I'):  return( 22 );
  432.                         case('L'):  return( 81 );
  433.                         case('M'):  return( 69 );
  434.                     }
  435.                     break;
  436.  
  437.         case('X'):  if( ch=='E' )
  438.                         return( 54 );
  439.                     break;
  440.  
  441.         case('Y'):  if( ch=='B' )
  442.                         return( 70 );
  443.                     break;
  444.  
  445.         case('Z'):  if( ch=='N' )
  446.                     {   return( 30 );
  447.                     } else if( ch=='R' )
  448.                         return( 40 );
  449.                     break;
  450.     }
  451.  
  452.     if( (*ptr>='0') && (*ptr<='9') )
  453.         if( (ch=='H') || (ch=='D') )
  454.             return( 1 ); /* Hydrogen */
  455.  
  456.     return( 0 );
  457. }
  458.  
  459.  
  460. int ElemVDWRadius( elem )
  461.     int elem;
  462. {
  463.     if( !HasHydrogen )
  464.         switch( elem )
  465.         {   case(  6 ):  return( VDWCarbon );
  466.             case(  7 ):  return( VDWNitrogen );
  467.             case(  8 ):  return( VDWOxygen );    
  468.             case( 16 ):  return( VDWSulphur );
  469.         }
  470.     return( Element[elem].vdwrad );
  471. }
  472.  
  473.  
  474. static int EvaluateProperty( prop )
  475.     int prop;
  476. {
  477.     switch( prop )
  478.     {   case( PropIdent ):    return( QAtom->serno );
  479.         case( PropXCord ):    return( (int)QAtom->xorg );
  480.         case( PropYCord ):    return( (int)QAtom->yorg );
  481.         case( PropZCord ):    return( (int)QAtom->zorg );
  482.         case( PropTemp ):     return( QAtom->temp );
  483.         case( PropName ):     return( QAtom->refno );
  484.         case( PropResId ):    return( QGroup->serno );
  485.         case( PropResName ):  return( QGroup->refno );
  486.         case( PropChain ):    return( QChain->ident );
  487.         case( PropSelect ):   return( QAtom->flag&SelectFlag );
  488.         case( PropElemNo ):   return( GetElemNumber(QAtom) );
  489.         case( PropRad ):      if( QAtom->flag&SphereFlag )
  490.                               {   return( QAtom->radius );
  491.                               } else return( 0 );
  492.  
  493.         
  494.         /* Predicates stored in flags */
  495.         case( PredBonded ):       return( !(QAtom->flag&NonBondFlag) );
  496.         case( PredHydrogen ):     return( QAtom->flag&HydrogenFlag );
  497.         case( PredHetero ):       return( QAtom->flag&HeteroFlag );
  498.         case( PredCystine ):      return( QGroup->flag&CystineFlag );
  499.         case( PredHelix ):        return( QGroup->struc&HelixFlag );
  500.         case( PredSheet ):        return( QGroup->struc&SheetFlag );
  501.         case( PredTurn ):         return( QGroup->struc&TurnFlag );
  502.  
  503.         /* Residue type predicates */
  504.         case( PredDNA ):
  505.         case( PredRNA ):
  506.         case( PredNucleic ):      return( IsNucleo(QGroup->refno) );
  507.         case( PredProtein ):      return( IsProtein(QGroup->refno) );
  508.         case( PredAmino ):        return( IsAmino(QGroup->refno) );
  509.         case( PredWater ):        return( IsWater(QGroup->refno) );
  510.         case( PredSolvent ):      return( IsSolvent(QGroup->refno) );
  511.         case( PredIon ):          return( IsIon(QGroup->refno) );
  512.  
  513.         /* General Predicates */
  514.         case( PredAlpha ):        return( IsAmino(QGroup->refno) &&
  515.                                           IsAlphaCarbon(QAtom->refno) );
  516.         case( PredMainChain ):    return( (IsAmino(QGroup->refno) && 
  517.                                            IsAminoBackbone(QAtom->refno)) ||
  518.                                           (IsNucleo(QGroup->refno) &&
  519.                                            IsNucleicBackbone(QAtom->refno)) );
  520.         case( PredSidechain ):    return( IsAmino(QGroup->refno) &&
  521.                                           !IsAminoBackbone(QAtom->refno) );
  522.         case( PredLigand ):       return( (QAtom->flag&HeteroFlag) &&
  523.                                           !IsSolvent(QGroup->refno) );
  524.  
  525.         /* Nucleic Acid Classifications */
  526.         case( PredAT ):           return( IsAdenine(QGroup->refno) ||
  527.                                           IsThymine(QGroup->refno) );
  528.         case( PredCG ):           return( IsCytosine(QGroup->refno) ||
  529.                                           IsGuanine(QGroup->refno) );
  530.         case( PredPyrimidine ):   return( IsPyrimidine(QGroup->refno) );
  531.         case( PredPurine ):       return( IsPurine(QGroup->refno) );
  532.  
  533.  
  534.         /* Amino Acid Classifications */
  535.         case( PredAcidic ):       return( IsAmino(QGroup->refno) &&
  536.                                   AminoProp[QGroup->refno]&BitAcidic );
  537.  
  538.         case( PredAcyclic ):      return( IsAmino(QGroup->refno) &&
  539.                                   !(AminoProp[QGroup->refno]&BitCyclic) );
  540.  
  541.         case( PredAliphatic ):    return( IsAmino(QGroup->refno) &&
  542.                                   AminoProp[QGroup->refno]&BitAliphatic );
  543.  
  544.         case( PredAromatic ):     return( IsAmino(QGroup->refno) &&
  545.                                   AminoProp[QGroup->refno]&BitAromatic );
  546.  
  547.         case( PredBasic ):        return( IsAmino(QGroup->refno) &&
  548.                                   AminoProp[QGroup->refno]&BitBasic );
  549.  
  550.         case( PredBuried ):       return( IsAmino(QGroup->refno) &&
  551.                                   AminoProp[QGroup->refno]&BitBuried );
  552.  
  553.         case( PredCharged ):      return( IsAmino(QGroup->refno) &&
  554.                                   AminoProp[QGroup->refno]&BitCharged );
  555.  
  556.         case( PredCyclic ):       return( IsAmino(QGroup->refno) &&
  557.                                   AminoProp[QGroup->refno]&BitCyclic );
  558.  
  559.         case( PredHydrophobic ):  return( IsAmino(QGroup->refno) &&
  560.                                   AminoProp[QGroup->refno]&BitHydrophobic );
  561.                  
  562.         case( PredLarge ):        return( IsAmino(QGroup->refno) &&
  563.                                   !(AminoProp[QGroup->refno]&BitNotLarge) );
  564.  
  565.         case( PredMedium ):       return( IsAmino(QGroup->refno) &&
  566.                                   AminoProp[QGroup->refno]&BitMedium );
  567.  
  568.         case( PredNeutral ):      return( IsAmino(QGroup->refno) &&
  569.                                   AminoProp[QGroup->refno]&BitNeutral );
  570.  
  571.         case( PredPolar ):        return( IsAmino(QGroup->refno) &&
  572.                                   !(AminoProp[QGroup->refno]&BitHydrophobic) );
  573.  
  574.         case( PredSmall ):        return( IsAmino(QGroup->refno) &&
  575.                                   AminoProp[QGroup->refno]&BitSmall );
  576.  
  577.         case( PredSurface ):      return( IsAmino(QGroup->refno) &&
  578.                                   !(AminoProp[QGroup->refno]&BitBuried) );
  579.  
  580.     }
  581.     return( True );
  582. }
  583.  
  584.  
  585. int EvaluateExpr( expr )
  586.     Expr *expr;
  587. {
  588.     register int lft, rgt;
  589.  
  590.     if( !expr )
  591.         return( True );
  592.  
  593.     if( expr->type==OpWithin )
  594.     {   if( expr->lft.limit )
  595.         {   return( IsWithinRadius(expr->rgt.set,expr->lft.limit) );
  596.         } else return( IsSetMember(expr->rgt.set) );
  597.     } else if( expr->type==OpMember )
  598.         return( IsSetMember(expr->rgt.set) );
  599.  
  600.     if( expr->type & OpLftVal )
  601.     {   lft = expr->lft.val;
  602.     } else if( expr->type & OpLftProp )
  603.     {   lft = EvaluateProperty( expr->lft.val );
  604.     } else lft = EvaluateExpr( expr->lft.ptr );
  605.  
  606.     if( OpCode(expr)==OpConst ) return( lft );
  607.     if( (OpCode(expr)==OpAnd) && !lft ) return( False );
  608.     if( (OpCode(expr)==OpOr) && lft ) return( True );
  609.     if( OpCode(expr)==OpNot ) return( !lft );
  610.  
  611.     if( expr->type & OpRgtVal )
  612.     {   rgt = expr->rgt.val;
  613.     } else if( expr->type & OpRgtProp )
  614.     {   rgt = EvaluateProperty( expr->rgt.val );
  615.     } else rgt = EvaluateExpr( expr->rgt.ptr );
  616.  
  617.     switch( OpCode(expr) )
  618.     {   case(OpOr):
  619.         case(OpAnd):     return( rgt );
  620.         case(OpLess):    return( lft<rgt );
  621.         case(OpMore):    return( lft>rgt );
  622.         case(OpEqual):   return( lft==rgt );
  623.         case(OpNotEq):   return( lft!=rgt );
  624.         case(OpLessEq):  return( lft<=rgt );
  625.         case(OpMoreEq):  return( lft>=rgt );
  626.     }
  627.     return( True );
  628. }
  629.  
  630.  
  631. AtomSet __far *BuildAtomSet( expr )
  632.     Expr *expr;
  633. {
  634.     register AtomSet __far *ptr;
  635.  
  636.     ptr = (AtomSet __far*)0;
  637.  
  638.     if( Database )
  639.         for( QChain=Database->clist; QChain; QChain=QChain->cnext )
  640.             for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext )
  641.                 for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext )
  642.                     if( EvaluateExpr(expr) )
  643.                         ptr = SetInsert( ptr, QAtom );
  644.  
  645.     return( ptr );
  646. }
  647.  
  648.  
  649.  
  650. int DefineSetExpr( ident, expr )
  651.     char *ident;  Expr *expr;
  652. {
  653.     register SymEntry __far * __far *prev;
  654.     register SymEntry __far *ptr;
  655.     register AtomSet __far *set;
  656.     register int result;
  657.  
  658.     result = True;
  659.     prev = &SymbolTable;
  660.     while( (ptr = *prev) )
  661.     {   result = strcmp(ident,ptr->ident);
  662.         if( !result ) break;  /* Entry Exists! */
  663.         prev = (result<0)? &(ptr->lft) : &(ptr->rgt);
  664.     }
  665.  
  666.     if( result )
  667.     {   if( FreeEntry )
  668.         {   ptr = FreeEntry;
  669.             FreeEntry = ptr->rgt;
  670.         } else /* Allocate SymEntry! */
  671.             if( !(ptr = (SymEntry __far*)_fmalloc(sizeof(SymEntry))) )
  672.                 return( False );
  673.  
  674.         *prev = ptr;
  675.         ptr->ident = ident;
  676.         ptr->defn = (void __far*)0;
  677.         ptr->lft = (void __far*)0;
  678.         ptr->rgt = (void __far*)0;
  679.     } else free(ident);
  680.  
  681.     if( expr )
  682.     {   set = BuildAtomSet(expr);
  683.         if( ptr->defn )
  684.             DeleteAtomSet(ptr->defn);
  685.         DeAllocateExpr(expr);
  686.         ptr->defn = set;
  687.     } else ptr->defn = (void __far*)0;
  688.     return( True );
  689. }
  690.  
  691.  
  692. Expr *LookUpSetExpr( ident )
  693.     char *ident;
  694. {
  695.     register SymEntry __far *ptr;
  696.     register Expr *expr;
  697.     register int result;
  698.  
  699.     result = True;
  700.     ptr = SymbolTable;
  701.     while( ptr )
  702.     {   result = strcmp(ident,ptr->ident);
  703.         if( !result ) break;  /* Entry Exists! */
  704.         ptr = (result<0)? ptr->lft : ptr->rgt;
  705.     }
  706.  
  707.     if( !result )
  708.     {   expr = AllocateNode();
  709.         expr->type = OpMember;
  710.         expr->rgt.set = ptr->defn;
  711.     } else expr = (Expr*)0;
  712.     return( expr );
  713. }
  714.  
  715.  
  716. static int ElemCompare( ident, elem )
  717.     char *ident, *elem;
  718. {
  719.     while( *elem )
  720.         if( *elem++ != *ident++ )
  721.             return( False );
  722.  
  723.     /* Handle Plurals */
  724.     if( (ident[0]=='S') && !ident[1] )
  725.         return( (elem[-1]!='S') && (elem[-1]!='Y') );
  726.     return( !*ident );
  727. }
  728.  
  729.  
  730. Expr *LookUpElement( ident )
  731.     char *ident;
  732. {
  733.     register Expr *expr;
  734.     register int elem;
  735.  
  736.     for( elem=1; elem<MAXELEMNO; elem++ )
  737.         if( ElemCompare(ident,Element[elem].name) )
  738.             break;
  739.  
  740.     /* Handle Difficult Plurals & US Spelling! */
  741.     if( elem == MAXELEMNO )
  742.     {   if( *ident=='A' )
  743.         {   if( ElemCompare(ident,"ALUMINUM") )
  744.             {   elem = 13;
  745.             } else if( !strcmp(ident,"ANTIMONIES") )
  746.                 elem = 51;
  747.         } else if( *ident=='C' )
  748.         {   if( ElemCompare(ident,"CESIUM") )
  749.                 elem = 55;
  750.         } else if( *ident=='M' )
  751.         {   if( !strcmp(ident,"MERCURIES") )
  752.                 elem = 80;
  753.         } else if( *ident=='P' )
  754.         {   if( !strcmp(ident,"PHOSPHORUSES") )
  755.                 elem = 8;
  756.         } else if( *ident=='S' )
  757.         {   if( ElemCompare(ident,"SULFUR") )
  758.                 elem = 16;
  759.         }
  760.     }
  761.  
  762.     if( elem<MAXELEMNO )
  763.     {   expr = AllocateNode();
  764.         expr->type = OpEqual|OpLftProp|OpRgtVal;
  765.         expr->lft.val = PropElemNo;
  766.         expr->rgt.val = elem;
  767.     } else expr = (Expr*)0;
  768.     return( expr );
  769. }
  770.  
  771.  
  772.  
  773. static int MatchWildName( src, dst, size, len )
  774.     char *src, *dst; int size, len;
  775. {
  776.     register int i, left;
  777.  
  778.     left = size;
  779.     while( *dst==' ' )
  780.     {   dst++; left--;
  781.     }
  782.  
  783.     for( i=0; i<len; i++ )
  784.     {   if( left )
  785.         {   if( (*dst==*src) || (*src=='?') )
  786.             {   dst++;  src++;  left--;
  787.             } else return( False );
  788.         } else if( *src++ != '?' )
  789.             return( False );
  790.     }
  791.  
  792.     while( left )
  793.          if( *dst++!=' ' )
  794.          {   return( False );
  795.          } else left--;
  796.     return( True );
  797. }
  798.  
  799.  
  800.  
  801. int ParsePrimitiveExpr( orig )
  802.     char **orig;
  803. {
  804.     static char NameBuf[4];
  805.     register Expr *tmp1,*tmp2;
  806.     register Expr *wild;
  807.     register char *ptr;
  808.     register int i, j;
  809.     register int neg;
  810.     register int ch;
  811.     
  812.     QueryExpr = &TrueExpr;
  813.     ptr = *orig;
  814.     ch = *ptr++;
  815.     i = 0;
  816.  
  817.     if( ch != '*' )
  818.     {   if( ch == '[' )
  819.         {   i = 0;
  820.             while( (ch = *ptr++) != ']' )
  821.                 if( ch && (i<3) )
  822.                 {   NameBuf[i++] = ToUpper(ch);
  823.                 } else return( False );
  824.             ch = *ptr++;
  825.         } else
  826.             for( i=0; i<3; i++ )
  827.                 if( isalpha(ch) )
  828.                 {   NameBuf[i] = ToUpper(ch);
  829.                     ch = *ptr++;
  830.                 } else if( (ch=='?') || (ch=='%') )
  831.                 {   NameBuf[i] = '?';
  832.                     ch = *ptr++;
  833.                 } else break;
  834.         if( !i ) return( False );
  835.  
  836.         wild = &FalseExpr;
  837.         for( j=0; j<ResNo; j++ )
  838.             if( MatchWildName(NameBuf,Residue[j],3,i) )
  839.             {   tmp1 = AllocateNode();
  840.                 tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  841.                 tmp1->lft.val = PropResName;
  842.                 tmp1->rgt.val = j;
  843.  
  844.                 tmp2 = AllocateNode();
  845.                 tmp2->type = OpOr;
  846.                 tmp2->lft.ptr = tmp1;
  847.                 tmp2->rgt.ptr = wild;
  848.                 wild = tmp2;
  849.             }
  850.         QueryExpr = wild;
  851.     } else ch = *ptr++;
  852.  
  853.     if( ch != '*' )
  854.     {   if( ch == '-' )
  855.         {   ch = *ptr++;
  856.             neg = True;
  857.         } else neg = False;
  858.  
  859.         if( isdigit(ch) )
  860.         {   i = ch-'0';
  861.             while( isdigit(*ptr) )
  862.                 i = 10*i + (*ptr++)-'0';
  863.  
  864.             tmp1 = AllocateNode();
  865.             tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  866.             tmp1->rgt.val = neg? -i : i;
  867.             tmp1->lft.val = PropResId;
  868.             if( QueryExpr != &TrueExpr )
  869.             {   tmp2 = AllocateNode();
  870.                 tmp2->type = OpAnd;
  871.                 tmp2->rgt.ptr = QueryExpr;
  872.                 tmp2->lft.ptr = tmp1;
  873.                 QueryExpr = tmp2;
  874.             } else QueryExpr = tmp1;
  875.             ch = *ptr++;
  876.         } else if( neg )
  877.             return( False );
  878.     } else ch = *ptr++;
  879.  
  880.     if( ch==':' )
  881.         ch = *ptr++;
  882.  
  883.     if( isalnum(ch) )
  884.     {   ch = ToUpper(ch);
  885.  
  886.         tmp1 = AllocateNode();
  887.         tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  888.         tmp1->lft.val = PropChain;
  889.         tmp1->rgt.val = ch;
  890.         if( QueryExpr != &TrueExpr )
  891.         {   tmp2 = AllocateNode();
  892.             tmp2->type = OpAnd;
  893.             tmp2->rgt.ptr = QueryExpr;
  894.             tmp2->lft.ptr = tmp1;
  895.             QueryExpr = tmp2;
  896.         } else QueryExpr = tmp1;
  897.         ch = *ptr++;
  898.     } else if( (ch=='?') || (ch=='%') || (ch=='*') )
  899.         ch = *ptr++;
  900.  
  901.     if( ch == '.' )
  902.     {   ch = *ptr++;
  903.         if( ch!='*' )
  904.         {   for( i=0; i<4; i++ )
  905.                 if( isalnum(ch) || ch=='\'' || ch=='*' )
  906.                 {   NameBuf[i] = ToUpper(ch);
  907.                     ch = *ptr++;
  908.                 } else if( (ch=='?') || (ch=='%') || (ch=='#') )
  909.                 {   NameBuf[i] = '?';
  910.                     ch = *ptr++;
  911.                 } else break;
  912.             if( !i ) return( False );
  913.  
  914.  
  915.             wild = &FalseExpr;
  916.             for( j=0; j<ElemNo; j++ )
  917.                 if( MatchWildName(NameBuf,ElemDesc[j],4,i) )
  918.                 {   tmp1 = AllocateNode();
  919.                     tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  920.                     tmp1->lft.val = PropName;
  921.                     tmp1->rgt.val = j;
  922.  
  923.                     tmp2 = AllocateNode();
  924.                     tmp2->type = OpOr;
  925.                     tmp2->lft.ptr = tmp1;
  926.                     tmp2->rgt.ptr = wild;
  927.                     wild = tmp2;
  928.                 }
  929.  
  930.             if( (QueryExpr == &TrueExpr) || (wild == &FalseExpr) )
  931.             {   DeAllocateExpr(QueryExpr);
  932.                 QueryExpr=wild;
  933.             } else
  934.             {   tmp1 = AllocateNode();
  935.                 tmp1->type = OpAnd;
  936.                 tmp1->lft.ptr = QueryExpr;
  937.                 tmp1->rgt.ptr = wild;
  938.                 QueryExpr = tmp1;
  939.             }
  940.         } else ch = *ptr++;
  941.     }
  942.     *orig = --ptr;
  943.     return( !ch || isspace(ch) || ispunct(ch) );
  944. }
  945.  
  946.  
  947. static char *FormatInteger( ptr, value )
  948.     char *ptr; int value;
  949. {
  950.     auto char buffer[10];
  951.     register char *tmp;
  952.  
  953.     if( value<0 )
  954.     {   value = -value;
  955.         *ptr++ = '-';
  956.     }
  957.  
  958.     if( value>9 )
  959.     {   tmp = buffer;
  960.         while( value>9 )
  961.         {   *tmp++ = (value%10) + '0';
  962.             value /= 10;
  963.         }
  964.  
  965.         *ptr++ = value + '0';
  966.         do { tmp--; 
  967.             *ptr++ = *tmp;
  968.         } while( tmp != buffer );
  969.     } else *ptr++ = value + '0';
  970.     return( ptr );
  971. }
  972.  
  973.  
  974. void FormatLabel( chain, group, aptr, label, ptr )
  975.     Chain __far *chain;
  976.     Group __far *group;
  977.     Atom __far *aptr;
  978.     char *label, *ptr;
  979. {
  980.     register char ch;
  981.     register int i,j;
  982.  
  983.     while( ch = *label++ )
  984.        if( ch=='%' )
  985.        {   ch = *label++;
  986.            if( isupper(ch) )
  987.              ch = tolower(ch);
  988.  
  989.            switch( ch )
  990.            {   case('a'):  /* Atom Name */
  991.                            i = aptr->refno;
  992.                            for( j=0; j<4; j++ )
  993.                                if( ElemDesc[i][j]!=' ' )
  994.                                    *ptr++ = ElemDesc[i][j];
  995.                            break;
  996.  
  997.                case('b'):  /* Temperature/B-factor */
  998.                case('t'):  ptr = FormatInteger(ptr,aptr->temp);
  999.                            break;
  1000.  
  1001.                case('c'):  /* Chain Identifier */
  1002.                case('s'):  *ptr++ = chain->ident;
  1003.                            break;
  1004.  
  1005.                case('e'):  /* Element Type */
  1006.                            i = GetElemNumber(aptr);
  1007.                            *ptr++ = Element[i].symbol[0];
  1008.                            if( Element[i].symbol[1]!=' ' )
  1009.                                *ptr++ = Element[i].symbol[1];
  1010.                            break;
  1011.  
  1012.                case('i'):  /* Atom Number */
  1013.                            ptr = FormatInteger(ptr,aptr->serno);
  1014.                            break;
  1015.  
  1016.                case('n'):  /* Residue Name   */
  1017.                            i = group->refno;
  1018.                            for( j=0; j<3; j++ )
  1019.                                if( Residue[i][j]!=' ' )
  1020.                                    *ptr++ = Residue[i][j];
  1021.                            break;
  1022.  
  1023.                case('r'):  /* Residue Number */
  1024.                            ptr = FormatInteger(ptr,group->serno);
  1025.                            break;
  1026.  
  1027.                case('%'):  *ptr++ = '%';
  1028.                            break;
  1029.            }
  1030.        } else if( (ch>=' ') && (ch<='~') )
  1031.            *ptr++ = ch;
  1032.     *ptr = '\0';
  1033. }
  1034.  
  1035.  
  1036. #ifdef FUNCPROTO
  1037. /* Function Prototypes */
  1038. static void DeleteSymEntry( SymEntry __far* );
  1039. #endif
  1040.  
  1041.  
  1042. static void DeleteSymEntry( ptr )
  1043.     SymEntry __far *ptr;
  1044. {
  1045.     if( ptr->lft )
  1046.         DeleteSymEntry( ptr->lft );
  1047.     if( ptr->rgt )
  1048.         DeleteSymEntry( ptr->rgt );
  1049.  
  1050.     if( ptr->defn )
  1051.         DeleteAtomSet( ptr->defn );
  1052.     free( ptr->ident );
  1053.  
  1054.     ptr->rgt = FreeEntry;
  1055.     FreeEntry = ptr;
  1056. }
  1057.  
  1058.  
  1059. void ResetSymbolTable()
  1060. {
  1061.     if( SymbolTable )
  1062.     {   DeleteSymEntry(SymbolTable);
  1063.         SymbolTable = (void __far*)0;
  1064.     }
  1065. }
  1066.  
  1067.  
  1068. void InitialiseAbstree()
  1069. {
  1070.     FalseExpr.type = OpConst | OpLftVal | OpRgtVal;
  1071.     FalseExpr.rgt.val = FalseExpr.lft.val = 0;
  1072.  
  1073.     TrueExpr.type = OpConst | OpLftVal | OpRgtVal;
  1074.     TrueExpr.rgt.val = TrueExpr.lft.val = 1;
  1075.  
  1076.     QChain = (void __far*)0;
  1077.     QGroup = (void __far*)0;
  1078.     QAtom = (void __far*)0;
  1079.  
  1080.     SymbolTable = (void __far*)0;
  1081.  
  1082.     FreeEntry = (void __far*)0;
  1083.     FreeSet = (void __far*)0;
  1084.     FreeExpr = NULL;
  1085. }
  1086.